using System.Globalization;
using Microsoft.Win32;

namespace FscNET.Tracing
{
    public static class OutputManager
    {
        public const string REG_PATH = "Software\\Fabasoft\\TRACER\\Output";
        private static RegistryKey _keyTraceOutput;
        private static TraceOutput _traceOutput;

        //public static event FscNET.Tracer.Action OutputChanged;

        public static TraceOutput TraceOutput
        {
            get { return _traceOutput; }
            set
            {
                if (_traceOutput != (value & TraceOutput.All))
                {
                    _traceOutput = value & TraceOutput.All;

                    _outputCount = GetOutputCount();

                    //System.EventHandler temp = OutputChanged;
                    //if (temp != null) temp();

                    //write value to memory-mapped file
                    using(CMemoryMappedFile file = new CMemoryMappedFile("CooTraceMap"))
                        file.WriteInt32((int)_traceOutput);
                    SetRegistryKeyVal(_traceOutput);
                }
            }
        }

        private static TraceOutput GetRegistryKeyVal()
        {
            if ((_keyTraceOutput = Registry.CurrentUser.OpenSubKey(
                REG_PATH, RegistryKeyPermissionCheck.ReadSubTree)) != null)
            {
                int dummy;
                int.TryParse((string) _keyTraceOutput.GetValue(null), out dummy);
                _keyTraceOutput.Close();
                return (TraceOutput)dummy;
            }
            return TraceOutput.Default;
        }

        private static void SetRegistryKeyVal(TraceOutput outputValue)
        {
            if ((_keyTraceOutput = Registry.CurrentUser.CreateSubKey(
                REG_PATH, RegistryKeyPermissionCheck.ReadWriteSubTree)) != null)
            {
                _keyTraceOutput.SetValue(null, ((int) outputValue).ToString(CultureInfo.InvariantCulture));
                _keyTraceOutput.Close();
            }
        }

        private static int GetOutputCount()
        {
            int onCount = 0;
            for (int i = 0; i < sizeof(int) * 8; i++)
                if (((int)_traceOutput & (1 << i)) != 0) onCount++;
            return onCount;
        }

        private static int _outputCount;
        public static int OutputCount
        {
            get { return _outputCount; }
        }

        public static bool Process { get { return (_traceOutput & TraceOutput.Process) != 0; } }
        public static bool Thread { get { return (_traceOutput & TraceOutput.Thread) != 0; } }
        public static bool Module { get { return (_traceOutput & TraceOutput.Module) != 0; } }
        public static bool Project { get { return (_traceOutput & TraceOutput.Project) != 0; } }
        public static bool Function { get { return (_traceOutput & TraceOutput.Function) != 0; } }
        public static bool File { get { return (_traceOutput & TraceOutput.File) != 0; } }
        public static bool Line { get { return (_traceOutput & TraceOutput.Line) != 0; } }
        public static bool Stack { get { return (_traceOutput & TraceOutput.Stack) != 0; } }
        public static bool User { get { return (_traceOutput & TraceOutput.User) != 0; } }

        static OutputManager()
        {

            RefreshValue();
        }

        public static void RefreshValue()
        {
            _traceOutput = GetRegistryKeyVal() & TraceOutput.All;
            _outputCount = GetOutputCount();
        }
    }
}
